/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.pbs.dao;

import br.com.pbs.exeptions.BancoExeption;
import br.com.pbs.interfaces.Bean;
import br.com.pbs.interfaces.IGenericDao;
import br.com.pbs.util.HibernateUtil;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

/**
 *
 * @author heldonjose & Luiz Segundo
 * @param <T>: Objeto a armazenar
 * Classe DAO Generica para acesso ao banco
 */
public abstract class GenericDao<T extends Bean> implements IGenericDao<T> {

        protected Session session = null;
        protected Transaction transaction = null;
        //Logs log;

       
        public GenericDao() {
                //log = new Logs();
        }

        
        public void iniciaSession() {
                if (session == null || !session.isOpen()) {
                        session = HibernateUtil.getSessionFactory().openSession();
                }

        }

       
        public void iniciaTransaction() {
                if (transaction == null || !transaction.isActive()) {
                        transaction = session.beginTransaction();
                }

        }

        
        public void finaliza() {
                if (((transaction != null) && (session != null))) {
                        if (transaction.isActive() && session.isOpen()) {
                                transaction.commit();
                                session.close();
                        }
                }
        }

        
        public boolean save(T t) throws BancoExeption {
                try {
                        // log.info("Ininializando o metodo save . "+ t.getClass()+"\n");
                        this.iniciaSession();
                        this.verifica(t);
                        this.iniciaTransaction();
                        session.merge(t);
                        // log.info("Retornando a confirmação do save. "+ t.getClass()+"\n");
                        return true;
                } catch (Exception e) {
                        transaction.rollback();
                        //  log.info("Exeção no arquivo. "+ t.getClass()+"\n");
                        throw new BancoExeption("Erro ao tentar salvar o arquivo" + t.getClass());
                } finally {
                        //  log.info("Finalizando a sessão."+ t.getClass()+"\n");
                        this.finaliza();
                }
        }
       
        public boolean delete(T t) throws BancoExeption {
                try {
                        // log.info("Ininializando o metodo delete . "+ t.getClass()+"\n");
                        this.iniciaSession();
                        this.iniciaTransaction();
                        session.delete(t);
                        // log.info("Retornando a confirmação do delete. "+ t.getClass()+"\n");
                        return true;
                } catch (Exception e) {
                        transaction.rollback();
                        // log.info("Exeção no arquivo. "+ t.getClass()+"\n");
                        throw new BancoExeption("Erro ao tentar deletar o arquivo" + t.getClass());
                } finally {
                        //  log.info("Finalizando a sessão."+ t.getClass()+"\n");
                        this.finaliza();
                }

        }

        public boolean update(T t) throws BancoExeption {
                try {
                        this.iniciaSession();
                        verifica(t);
                        this.iniciaTransaction();
                        session.merge(t);
                        return true;
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar atualizar o arquivo " + t.getClass());
                } finally {
                        this.finaliza();
                }
        }

        public List<T> listaTodos(T t) throws BancoExeption {
                List<T> list = null;
                try {
                        this.iniciaSession();
                        this.iniciaTransaction();
                        Criteria c = session.createCriteria(t.getClass());
                        list = c.list();
                        return list;
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar listarTodos" + t.getClass());

                } finally {
                        this.finaliza();
                }

        }

        public T buscaPorId(long id, T t) throws BancoExeption {
                try {
                        this.iniciaSession();
                        this.iniciaTransaction();
                        Criteria c = session.createCriteria(t.getClass());
                        c.add(Restrictions.ilike("id", id));
                        t = (T) c.uniqueResult();
                        return t;
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar buscar por ID" + t.getClass());
                } finally {
                        this.finaliza();
                }

        }

        public T buscaObjetoPorNome(String nome, T t) throws BancoExeption {
                try {
                        this.iniciaSession();
                        this.iniciaTransaction();
                        Criteria c = session.createCriteria(t.getClass());
                        c.add(Restrictions.ilike("nome", nome));
                        t = (T) c.uniqueResult();
                        return t;
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar buscar por Nome" + t.getClass());
                } finally {
                        this.finaliza();
                }

        }

        @SuppressWarnings("unchecked")
        public List<T> listaDeNomes(String nome, T t) throws BancoExeption {
                try {
                        this.iniciaSession();
                        this.iniciaTransaction();
                        Criteria c = session.createCriteria(t.getClass());
                        c.add(Restrictions.ilike("nome", nome + "%"));
                        if (c.list() == null) {
                                throw new BancoExeption("Não foi encontrado");
                        }
                        return c.list();
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar buscar Lista de Nomes" + t.getClass());
                } finally {
                        this.finaliza();
                }
        }

        public List<T> buscaPorAtributoString(String atributo, String busca, T t) throws BancoExeption {
                try {
                        this.iniciaSession();
                        this.iniciaTransaction();
                        Criteria c = session.createCriteria(t.getClass());
                        c.add(Restrictions.ilike(atributo, "%" + busca + "%"));
                        if (c.list() == null) {
                                throw new BancoExeption("Não foi encontrado");
                        }
                        return c.list();
                } catch (Exception e) {
                        transaction.rollback();
                        throw new BancoExeption("Erro ao tentar buscar LIsta de " + atributo + t.getClass());
                } finally {
                        this.finaliza();
                }
        }
}
